package io.github.bloquesoft.entity.clazz;

import io.github.bloquesoft.entity.clazz.value.ObjectEntityValue;
import io.github.bloquesoft.entity.clazz.value.ObjectEntityValueFactory;
import io.github.bloquesoft.entity.storage.PojoOperation;
import io.github.bloquesoft.entity.storage.analysis.EntityAnalysis;
import io.github.bloquesoft.entity.storage.analysis.EntityAnalysisResult;
import io.github.bloquesoft.entity.storage.analysis.StorageEntityAnalysisResult;
import io.github.bloquesoft.entity.storage.finding.EntityFinding;
import io.github.bloquesoft.entity.storage.finding.PropertyTree;
import io.github.bloquesoft.entity.value.EntityValue;
import io.github.bloquesoft.entity.value.EntityValueFactory;

public class ClassEntityExecutorImpl implements ClassEntityExecutor {

    private final PojoOperation pojoOperation;

    private final ClassEntityDefinitionFactory classEntityDefinitionFactory;

    private final StorageEntityAnalysisResult storageEntityAnalysisResult;

    private final EntityValueFactory  entityValueFactory = new ObjectEntityValueFactory();

    public ClassEntityExecutorImpl(PojoOperation pojoOperation, ClassEntityDefinitionFactory classEntityDefinitionFactory, StorageEntityAnalysisResult storageEntityAnalysisResult) {
        this.pojoOperation = pojoOperation;
        this.classEntityDefinitionFactory = classEntityDefinitionFactory;
        this.storageEntityAnalysisResult = storageEntityAnalysisResult;
    }

    @Override
    public <T> void save(Class<T> clazz, T source, T target) {
        EntityAnalysis entityAnalysis = new EntityAnalysis();
        ClassEntityDefinition classEntityDefinition = this.classEntityDefinitionFactory.get(clazz);
        EntityValue sourceEntityValue = new ObjectEntityValue(classEntityDefinition, source, null);
        EntityValue targetEntityValue = new ObjectEntityValue(classEntityDefinition, target, null);
        EntityAnalysisResult result = entityAnalysis.analyze(sourceEntityValue , targetEntityValue);
        this.storageEntityAnalysisResult.storage(result, this.pojoOperation);
    }


    @Override
    public <T> T findOne(Class<T> clazz, Object id, PropertyTree tree)
    {
        ClassEntityDefinition classEntityDefinition = this.classEntityDefinitionFactory.get(clazz);
        EntityFinding entityFinding = new EntityFinding();
        EntityValue entityValue = entityFinding.findOne(classEntityDefinition, id,  tree, this.pojoOperation, this.entityValueFactory);
        return (T)entityValue.getValue();
    }
}
